package memory

import (
	"context"
	"time"

	"gitee.com/mkwchecking/sr-core/net/http/session"
	"gitee.com/mkwchecking/sr-core/storage/cache"
	"gitee.com/mkwchecking/sr-core/storage/cache/memory"
)

func init() {
	session.Register(session.SessionStoreTypeMemory, newSessionStoreFac)
}

var _ session.Storage = (*MemStore)(nil)

func newSessionStoreFac(ctx context.Context, cfg session.SessionConfig) (session.Storage, error) {

	cli, err := memory.NewCache(cache.Conn{})
	if err != nil {
		return nil, err
	}

	return &MemStore{
		cli: cli,
	}, nil
}

type MemStore struct {
	cli cache.ICache
}

// Data implements session.Storage.
func (r *MemStore) Data(ctx context.Context, sessionId string) (sessionData map[string]interface{}, err error) {
	val, err := r.cli.HashGet(ctx, sessionId)
	if err != nil {
		return nil, err
	}

	res := make(map[string]interface{})
	for k, v := range val {
		res[k] = v
	}
	return res, nil
}

// Get implements session.Storage.
func (r *MemStore) Get(ctx context.Context, sessionId string, key string) (value interface{}, err error) {
	val, err := r.cli.HashGet(ctx, sessionId)
	if err != nil {
		return nil, err
	}

	return val[key], nil
}

// GetSession implements session.Storage.
func (r *MemStore) GetSession(ctx context.Context, sessionId string, ttl time.Duration) (map[string]any, error) {
	val, err := r.cli.HashGet(ctx, sessionId)
	if err != nil {
		return nil, err
	}

	res := make(map[string]interface{})
	for k, v := range val {
		res[k] = v
	}
	return res, nil
}

// GetSize implements session.Storage.
func (r *MemStore) GetSize(ctx context.Context, sessionId string) (size int, err error) {
	val, err := r.GetSession(ctx, sessionId, 0)
	if err != nil {
		return 0, err
	}

	return len(val), nil
}

// Remove implements session.Storage.
func (r *MemStore) Remove(ctx context.Context, sessionId string, key string) error {
	return r.cli.HashDel(ctx, sessionId, key)
}

// RemoveAll implements session.Storage.
func (r *MemStore) RemoveAll(ctx context.Context, sessionId string) error {
	return r.cli.Delete(ctx, sessionId)
}

// Set implements session.Storage.
func (r *MemStore) Set(ctx context.Context, sessionId string, key string, value interface{}, ttl time.Duration) error {
	return r.cli.HashSet(ctx, sessionId, map[string]any{key: value}, ttl)
}

// SetMap implements session.Storage.
func (r *MemStore) SetMap(ctx context.Context, sessionId string, mapData map[string]interface{}, ttl time.Duration) error {
	return r.cli.HashSet(ctx, sessionId, mapData, ttl)
}

// SetSession implements session.Storage.
func (r *MemStore) SetSession(ctx context.Context, sessionId string, sessionData map[string]any, ttl time.Duration) error {
	return r.cli.HashSet(ctx, sessionId, sessionData, ttl)
}

// UpdateTTL implements session.Storage.
func (r *MemStore) UpdateTTL(ctx context.Context, sessionId string, ttl time.Duration) error {
	return r.cli.Expire(ctx, sessionId, ttl)
}
